#!/usr/bin/env python2.5

import datetime, hmac, sha, base64, urllib, simplejson

def _generateTimestamp():
    return "2008-06-28T17:26:08+00:00"
    #return datetime.datetime.utcnow().isoformat()[0:19]+"+00:00"

def _generateSignature(secret, params):
    signature = ""
    for key in sorted(params.keys(), key=str.lower):
        signature = signature + key + str(params[key])
    return base64.encodestring(hmac.new(secret, signature, sha).digest()).strip()

def _generateRequestUrl(endpoint, version, action, accessKey, secretKey, params):
    parameters = {}
    for key,value in params.iteritems():
        if type(value) in (list, tuple):
            for n,v in enumerate(value):
                parameters["%s.%d" % (key, n)] = v
        else:
            parameters[key] = str(value)
    parameters['Action'] = action
    parameters['Version'] = version
    if accessKey:
        parameters['AccessKey'] = accessKey
        parameters['SignatureVersion'] = "1"
        parameters['Timestamp'] = _generateTimestamp()
        parameters['Signature'] = _generateSignature(secretKey, parameters)
    return "%s?%s" % (endpoint, urllib.urlencode(parameters))

def executeCall(endpoint, version, action, accessKey = None, secretKey = None, parameters = {}):
    url = _generateRequestUrl(endpoint, version, action, accessKey, secretKey, parameters)
    print url
    response = urllib.urlopen(url).read()
    print response
    return simplejson.loads(response)

# The following are annotation based and under /api/one


print "\nExecuting BottlesOfBeer with NumberOfBottles=2"
json = executeCall('http://localhost:8080/private/api/one', '2008-04-01', 'BottlesOfBeer', 'TestAccount', 'SomeSecretKey',
    { 'NumberOfBottles': 2 })
for line in json['response']:
    print " %s" % line

print "\nExecuting BottlesOfBeer with no parameters"
json = executeCall('http://localhost:8080/private/api/one', '2008-04-01', 'BottlesOfBeer', 'TestAccount', 'SomeSecretKey')
if json.has_key('errors'):
    for error in json['errors']:
        print " Error: %s - %s" % (error['code'], error['description'])

print "\nExecuting BottlesOfBeer with NumberOfBottles=200"
json = executeCall('http://localhost:8080/private/api/one', '2008-04-01', 'BottlesOfBeer', 'TestAccount', 'SomeSecretKey',
    { 'NumberOfBottles': 200 })
if json.has_key('errors'):
    for error in json['errors']:
        print " Error: %s - %s" % (error['code'], error['description'])

# The following are 'bean-based' and under /private/api/two

print "Executing AddNumbers"
json = executeCall('http://localhost:8080/private/api/two', '2008-04-01', 'AddNumbers', 'TestAccount', 'SomeSecretKey',
    { 'Numbers': [1,2,3,4,5] })
print " %s" % json['response']

# The following are 'bean-based' and under /private/api/three

print "Executing ConcatStrings"
json = executeCall('http://localhost:8080/private/api/three', '2008-04-01', 'ConcatStrings', 'TestAccount', 'SomeSecretKey',
   { 'Strings': ['Hello', 'I\'ve waited here for you', 'Everlong'], 'Seperator': ' -- ' })
print " %s" % json['response']


print "\nExecuting GetCities"
json = executeCall('http://localhost:8080/private/api/three', '2008-04-01', 'GetCities', 'TestAccount', 'SomeSecretKey')
for city in json['response']:
    print " %s - %s" % (city['name'], city['population'])

print "\nExecuting GetCities with MinimalSize=2000000"
json = executeCall('http://localhost:8080/private/api/three', '2008-04-01', 'GetCities', 'TestAccount', 'SomeSecretKey',
    { 'MinimalSize': 2000000 })
for city in json['response']:
    print " %s - %s" % (city['name'], city['population'])

# The following are all public actions under /public/api with version 2008-06-27

print "\nExecuting SayHello"
json = executeCall('http://localhost:8080/public/api', '2008-06-27', 'SayHello', parameters = { 'Name': 'Stefan' })
print " %s" % json

print "\nExecuting GetMemoryInfo"
json = executeCall('http://localhost:8080/public/api', '2008-06-27', 'GetMemoryInfo')
print " Free memory  : %d" % json['response'][0]
print " Total memory : %d" % json['response'][1]
print " Max memory   : %d" % json['response'][2]

